package com.example.opengl.render.cube

import android.opengl.GLES20
import android.opengl.GLES20.*
import android.opengl.Matrix
import com.example.opengl.R
import com.example.opengl.base.BufferHelper
import com.example.opengl.base.ShaderHelper
import com.example.opengl.base.TextResourceReader
import com.example.opengl.render.base.IDrawer
import java.nio.ByteBuffer
import java.nio.FloatBuffer

/**
 * @author: Mr.You
 * @create: 2023-07-27 16:45
 * @description:
 **/
class CubeDrawer : IDrawer {

    val r = 1.0f
    val c = 1.0f

    var mProgram = -1
    var mScreenWidth = 0
    var mScreenHeight = 0
    var mVertexFloatBuffer: FloatBuffer? = null
    var mTextureFloatBuffer: FloatBuffer? = null
    var mFaceFloatBuffer: ByteBuffer? = null
    var mVertexShader = -1
    var mTextureShader = -1
    var mTextureID = -1

    var mRatio = 0f


    val mVertexCoords = floatArrayOf(
        r, r, r,
        -r, r, r,
        -r, -r, r,
        r, -r, r,
        r, r, -r,
        -r, r, -r,
        -r, -r, -r,
        r, -r, -r

    )
    val mFaceCoords = byteArrayOf(
        0, 2, 1, 0, 2, 3, //前面
        0, 5, 1, 0, 5, 4, //上面
        0, 7, 3, 0, 7, 4, //右面
        6, 4, 5, 6, 4, 7, //后面
        6, 3, 2, 6, 3, 7, //下面
        6, 1, 2, 6, 1, 5 //左面
    )
    val mTextureCoords = floatArrayOf(
        c, c, c, 0.5f,
        0f, c, c, 0.6f,
        0f, 0f, c, 0.7f,
        c, 0f, c, 0.4f,
        c, c, 0f, 0.3f,
        0f, c, 0f, 0.5f,
        0f, 0f, 0f, 1f,
        c, 0f, 0f, 0.6f
    )


    override fun draw() {
        if (mTextureID != -1) {
            initShader()
            doDraw()
        }
    }

    private fun initShader() {
        mVertexShader =
            ShaderHelper.compileVertexShader(TextResourceReader.readTextFileFormResource(resourceId = R.raw.vertex_cube_shader))
        mTextureShader =
            ShaderHelper.compileFragmentShader(TextResourceReader.readTextFileFormResource(resourceId = R.raw.fragment_cube_shader))
        mProgram = ShaderHelper.linkProgram(mVertexShader, mTextureShader)
        glUseProgram(mProgram)
        glDeleteShader(mVertexShader)
        glDeleteShader(mTextureShader)
    }

    private fun doDraw() {

        glClear(GL_COLOR_BUFFER_BIT and  GL_DEPTH_BUFFER_BIT)
        transform(mProgram,mRatio)
        glEnableVertexAttribArray(0)
        glEnableVertexAttribArray(1)
        glVertexAttribPointer(0, 3, GL_FLOAT, false, 0, mVertexFloatBuffer)
        glVertexAttribPointer(1, 4, GL_FLOAT, false, 0, mTextureFloatBuffer)

        //绘制表面
        glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_BYTE, mFaceFloatBuffer)

        glDisableVertexAttribArray(0)
        glDisableVertexAttribArray(1)


    }


    override fun setTextureID(id: Int) {
        mTextureID = id
    }

    override fun release() {

    }

    override fun setWorldSize(worldW: Int, worldH: Int) {
        mScreenWidth = worldW
        mScreenHeight = worldH
        mRatio = worldW / worldH.toFloat()
        glClearColor(1f,0f,0f,1f)
        glEnable(GL_DEPTH_BUFFER_BIT)
        initCoords()
    }

    private fun initCoords() {
        mVertexFloatBuffer = BufferHelper.getFloatBuffer(mVertexCoords)
        mTextureFloatBuffer = BufferHelper.getFloatBuffer(mTextureCoords)
        mFaceFloatBuffer = BufferHelper.getByteBuffer(mFaceCoords)
    }


    override fun setVideoSize(videoW: Int, videoH: Int) {

    }

    var mAngle = 0f
    private fun transform(mProgram: Int, ration: Float) {
        val modelMatrix = getUnitMatrix(16, 0)
        val viewMatrix = getUnitMatrix(16, 0)
        val projectMatrix = getUnitMatrix(16, 0)
        mAngle = (mAngle + 2) % 360f
        Matrix.rotateM( modelMatrix,0,mAngle,1f,1f,1f)
        Matrix.setLookAtM(viewMatrix,0,0f,5f,10f,0f,0f,0f,0f,1f,0f)
        Matrix.frustumM(projectMatrix,0,-ration,ration,-1f,1f,3f,20f)

        val mvpMatrix = FloatArray(16)
        Matrix.multiplyMM(mvpMatrix,0,viewMatrix,0,modelMatrix,0)
        Matrix.multiplyMM(mvpMatrix,0,projectMatrix,0,mvpMatrix,0)
        //获取mvpMatrix的位置下标
       val mvpHandler =  glGetUniformLocation(mProgram,"mvpMatrix")
        //将MVP矩阵加载到统一变量中
        glUniformMatrix4fv(mvpHandler,1,false,mvpMatrix,0)


    }

    /**
     * 创建单位矩阵
     */
    private fun getUnitMatrix(size: Int, offset: Int): FloatArray {
        var floatArray = FloatArray(size)
        Matrix.setIdentityM(floatArray, offset)
        return floatArray
    }
}